extern "C"
{
#include "md5.h"
}
#include "md5cpp.h"
using namespace std;



// half byte to hex
// @hb Only use low 4 bits
static char hb2hex ( unsigned char hb ) {
   hb = hb & 0xF;
   return hb < 10 ? '0' + hb : hb - 10 + 'a';
}
std::string hex2string ( const std::string &hex ) {
   string res;
   for ( auto ch : hex ){
      res.push_back ( hb2hex ( ch >> 4 ) );
      res.push_back ( hb2hex ( ch ) );
   }
   return res;
}


string md5sum ( const void* dat, size_t len ) {
   string res;
   unsigned char out[16];
   md5bin ( dat, len, out );
   for ( size_t i = 0; i < 16; ++i ) {
      res.push_back ( hb2hex ( out[i] >> 4 ) );
      res.push_back ( hb2hex ( out[i] ) );
   }
   return res;
}

void md5bin ( const void* dat, size_t len, unsigned char out[16] ) {
   MD5_CTX c;
   MD5_Init ( &c );
   MD5_Update ( &c, ( void* ) dat, len );
   MD5_Final ( out, &c );
}

string md5sum6 ( const void* dat, size_t len ) {
   static const char* tbl = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
   string res;
   unsigned char out[16];
   md5bin ( dat, len, out );
   for ( size_t i = 0; i < 6; ++i ) {
      res.push_back ( tbl[out[i] % 62] );
   }
   return res;
}